package activities;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import com.iculture.R;

import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.TextView;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

public class ScheduleActivity extends GlobalActivity implements SensorEventListener {
	private Button buttonNowYearAndMonth;
	private ViewPager schedulePager;
	private SparseArray<View> scheduleViewTable = new SparseArray<View>();
	private Calendar nowCal = Calendar.getInstance();
	private Calendar specificDay = Calendar.getInstance();
	private int schViewSize = 1000;
	private int schViewInitPosition = schViewSize / 2;
	private int currentSchViewIndex = schViewInitPosition;
	private int preHandleSchViewNum = 3;
	private int schViewMinIndex = currentSchViewIndex - preHandleSchViewNum;
	private int schViewMaxIndex = currentSchViewIndex + preHandleSchViewNum;
	private SensorManager sensorManager;
	private boolean isToday = true;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_schedule);
		findView();
		setListenerOrAdapter();
		buttonSchedule.setClickable(false);
		nowCal.add(Calendar.DAY_OF_WEEK, -(nowCal.get(Calendar.DAY_OF_WEEK) - 1));
		setButtonNowYearAndMonth();
		yieldScheduleTable();
		sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
	}

	@Override
	protected void findView() {
		super.findView();
		buttonNowYearAndMonth = (Button)findViewById(R.id.buttonNowYearAndMonth);
		schedulePager = (ViewPager)findViewById(R.id.schedulePager);
	}
	
	@Override
	protected void setListenerOrAdapter() {
		super.setListenerOrAdapter();
		buttonNowYearAndMonth.setOnClickListener(new ButtonNowYearAndMonthClickListener());
		schedulePager.setOnPageChangeListener(new SchedulePagerPageChangeListener());
		schedulePager.setAdapter(new SchedulePagerAdapter());
	}
	
	private class ButtonNowYearAndMonthClickListener implements Button.OnClickListener {
		private DatePicker specificDatePicker;
		
		@Override
		public void onClick(View arg0) {
			specificDatePicker = new DatePicker(ScheduleActivity.this);
			specificDatePicker.init(specificDay.get(Calendar.YEAR), specificDay.get(Calendar.MONTH), specificDay.get(Calendar.DATE), null);
			specificDatePicker.setCalendarViewShown(false);
			new AlertDialog.Builder(ScheduleActivity.this)
			.setTitle("選擇日期")
			.setView(specificDatePicker)
			.setNegativeButton(android.R.string.cancel, new DatePickerDialogNegativeOnClickListener())
			.setPositiveButton(android.R.string.ok, new DatePickerDialogPositiveOnClickListener())
			.show();
		}
		
		private class DatePickerDialogNegativeOnClickListener implements DialogInterface.OnClickListener {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			}
		}
		
		private class DatePickerDialogPositiveOnClickListener implements DialogInterface.OnClickListener {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				gotoSpecificDay(specificDatePicker.getYear(), specificDatePicker.getMonth(), specificDatePicker.getDayOfMonth());
			}
		}
	}
	
	private void gotoSpecificDay(int theYear, int theMonth, int theDate) {
		Calendar displayCal = Calendar.getInstance();
		
		isToday = false;
		nowCal.set(theYear, theMonth, theDate);
		specificDay.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
		nowCal.add(Calendar.DAY_OF_WEEK, -(nowCal.get(Calendar.DAY_OF_WEEK) - 1));
		setButtonNowYearAndMonth();
		currentSchViewIndex = schViewInitPosition;
		schViewMinIndex = schViewInitPosition - preHandleSchViewNum;
		schViewMaxIndex = schViewInitPosition + preHandleSchViewNum;
		displayCal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
		displayCal.add(Calendar.WEEK_OF_MONTH, -preHandleSchViewNum);
		for (int i=schViewMinIndex; i<=schViewMaxIndex; i++)
			setScheduleTable(displayCal, scheduleViewTable.get(i));
		schedulePager.setCurrentItem(schViewInitPosition);
	}
	
	private class SchedulePagerPageChangeListener implements ViewPager.OnPageChangeListener {
		private boolean initFlag = false;
		
		@Override
		public void onPageScrollStateChanged(int arg0) {
		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
		}

		@Override
		public void onPageSelected(int newIndex) {
			if (initFlag) {
				if (newIndex > currentSchViewIndex) {
					nowCal.add(Calendar.WEEK_OF_MONTH, 1);
					setButtonNowYearAndMonth();
					currentSchViewIndex = newIndex;
					isToday = false;
					if (newIndex == schViewMaxIndex) {
						int newMaxIndex = schViewMaxIndex + preHandleSchViewNum;
						Calendar displayCal = Calendar.getInstance();
						
						displayCal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
						displayCal.add(Calendar.WEEK_OF_MONTH, 1);
						for (int i=schViewMaxIndex+1; i<=newMaxIndex; i++) {
							View schView;
							
							if (scheduleViewTable.get(i) == null)
								schView = getLayoutInflater().inflate(R.layout.scheduletable, null);
							else
								schView = scheduleViewTable.get(i);
							setScheduleTable(displayCal, schView);
							scheduleViewTable.put(i, schView);
						}
						schViewMaxIndex = newMaxIndex;
					}
				}
				else if (newIndex < currentSchViewIndex) {
					nowCal.add(Calendar.WEEK_OF_MONTH, -1);
					setButtonNowYearAndMonth();
					currentSchViewIndex = newIndex;
					isToday = false;
					if (newIndex == schViewMinIndex) {
						Calendar displayCal = Calendar.getInstance();
						int newMinIndex = schViewMinIndex - preHandleSchViewNum;
						
						displayCal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
						displayCal.add(Calendar.WEEK_OF_MONTH, -preHandleSchViewNum);
						for (int i=newMinIndex; i<schViewMinIndex; i++) {
							View schView;
							
							if (scheduleViewTable.get(i) == null)
								schView = getLayoutInflater().inflate(R.layout.scheduletable, null);
							else
								schView = scheduleViewTable.get(i);
							setScheduleTable(displayCal, schView);
							scheduleViewTable.put(i, schView);
						}
						schViewMinIndex = newMinIndex;
					}
				}
			}
			else
				initFlag = true;
		}
	}
	
	private class SchedulePagerAdapter extends PagerAdapter {
		
		@Override
		public void destroyItem(View arg0, int arg1, Object arg2) {
			((ViewPager) arg0).removeView(scheduleViewTable.get(arg1));
		}

		@Override
		public int getCount() {
			return schViewSize;
		}

		@Override
		public Object instantiateItem(View arg0, int arg1) {
			((ViewPager) arg0).addView(scheduleViewTable.get(arg1), 0);
			return scheduleViewTable.get(arg1);
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}
    }
	
	private void setButtonNowYearAndMonth() {
		Calendar displayCal = Calendar.getInstance();
		String yearAndMonth;
		int startMonth;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM", Locale.getDefault());
		
		displayCal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
		startMonth = displayCal.get(Calendar.MONTH);
		yearAndMonth = sdf.format(displayCal.getTime());
		displayCal.add(Calendar.DATE, 6);
		if (startMonth != displayCal.get(Calendar.MONTH))
			yearAndMonth += "~" + sdf.format(displayCal.getTime());
		buttonNowYearAndMonth.setText(yearAndMonth);
	}
	
	private void yieldScheduleTable() {
		Calendar displayCal = Calendar.getInstance();
		
		displayCal.set(nowCal.get(Calendar.YEAR), nowCal.get(Calendar.MONTH), nowCal.get(Calendar.DATE));
		displayCal.add(Calendar.WEEK_OF_MONTH, -preHandleSchViewNum);
		for (int i=schViewMinIndex; i<=schViewMaxIndex; i++) {
			View scheduleView = getLayoutInflater().inflate(R.layout.scheduletable, null);
			
			setScheduleTable(displayCal, scheduleView);
			scheduleViewTable.put(i, scheduleView);
		}
		schedulePager.setCurrentItem(schViewInitPosition);
	}
	
	private void setScheduleTable(Calendar displayCal, View scheduleView) {
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfSunday))),
				((TextView)(scheduleView.findViewById(R.id.textViewSunday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewSunday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfMonday))),
				((TextView)(scheduleView.findViewById(R.id.textViewMonday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewMonday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfTuesday))),
				((TextView)(scheduleView.findViewById(R.id.textViewTuesday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewTuesday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfWednesday))),
				((TextView)(scheduleView.findViewById(R.id.textViewWednesday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewWednesday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfThursday))),
				((TextView)(scheduleView.findViewById(R.id.textViewThursday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewThursday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfFriday))),
				((TextView)(scheduleView.findViewById(R.id.textViewFriday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewFriday))));
		displayCal.add(Calendar.DATE, 1);
		setEachDay(displayCal, ((TextView)(scheduleView.findViewById(R.id.textViewDateOfSaturday))),
				((TextView)(scheduleView.findViewById(R.id.textViewSaturday))), ((ImageView)(scheduleView.findViewById(R.id.imageViewSaturday))));
		displayCal.add(Calendar.DATE, 1);
	}
	
	private void setEachDay(Calendar displayCal, TextView dateText, TextView dayText, ImageView scheduleView) {
		String theDate = String.valueOf(displayCal.get(Calendar.DATE));
		
		if (isSameDay(displayCal, specificDay)) {
			dayText.setTextColor(getResources().getColor(R.color.red));
			dateText.setTextColor(getResources().getColor(R.color.red));
		}
		else {
			dayText.setTextColor(getResources().getColor(R.color.white));
			dateText.setTextColor(getResources().getColor(R.color.white));
		}
		dateText.setText(theDate);
		scheduleView.setOnClickListener(new ImageViewDayOnClickListener(displayCal.get(Calendar.MONTH) + 1, displayCal.get(Calendar.DATE)));
	}

	private class ImageViewDayOnClickListener implements ImageView.OnClickListener {
		private int month, date;

		public ImageViewDayOnClickListener(int month, int date) {
			this.month = month;
			this.date = date;
		}

		@Override
		public void onClick(View v) {
			String[] items = {"沒有行程"};
			
			new AlertDialog.Builder(ScheduleActivity.this).setTitle(month + "月" + date + "號").setItems(items, null).show();
		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		sensorManager.registerListener(ScheduleActivity.this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
	}
	
	@Override
    protected void onPause() {
		super.onPause();
		sensorManager.unregisterListener(ScheduleActivity.this);
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		if (!isToday && (event.values[0] > 10 || event.values[0] < -10)) {
			Calendar today = Calendar.getInstance();
			
			gotoSpecificDay(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DATE));
			isToday = true;
		}
	}
	
	private boolean isSameDay(Calendar theCal, Calendar otherCal) {
		return theCal.get(Calendar.YEAR) == otherCal.get(Calendar.YEAR)
				&& theCal.get(Calendar.MONTH) == otherCal.get(Calendar.MONTH) && theCal.get(Calendar.DATE) == otherCal.get(Calendar.DATE);
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}
}